#!/usr/bin/env python
#-------------------------------python-----------------------pyplot.py--#
#                                                                       #
#                    traccia grafici di funzioni                        #
#                                                                       #
#--Daniele Zambelli-----------License-GPL------------------------2007---#

#import sys
from math import *
from pycart import Plane

_pyplot_version = '02.03.02'

class Plot(Plane):
  """Class for plotting functions."""
  
  def __init__(self, name="PyPlot", 
               w=400, h=400, sx=20, sy=20, master=None):
    Plane.__init__(self, name, w, h, sx, sy, master)

  def version(self):
    return _pyplot_version

  def xy(self, f):
    """y=f(x).

    example:
      >>> p=Plot()
      >>> p.axes(True)
      >>> p.xy(".2*x*x+2*x-3")
    """
    primo=1; definito=1; inf_dom=self._s2x(0)
    for x1 in range(0, int(self.getcanvaswidth())):
      x=self._s2x(x1)
      try:
        y=eval(f)
        if primo:
          if not definito:
            inf_dom=x
            definito=1
          primo=0
          self.jump((x, y))
        else:
          self.setpos((x, y))
      except ZeroDivisionError, e:
        primo=1
        print "Probable asymptote for x =", x
      except ValueError, e:
        primo=1
        if definito:
          print "Defined from", inf_dom, "to", x
          definito=0
      except OverflowError, e:
        primo=1
    print "Defined from", inf_dom, "to", x

  def yx(self, f):
    """x=f(y).

    example:
      >>> p=Plot()
      >>> p.axes(True)
      >>> p.yx(".2*y*y+2*y-3")
    """
    primo=1; definito=1; inf_dom=self._s2y(0)
    altezza=int(self.getcanvasheight())
    for y1 in xrange(altezza):
      y=self._s2y(altezza-y1)
      try:
        x=eval(f)
        if primo:
          if not definito:
            inf_dom=y
            definito=1
          primo=0
          self.jump((x, y))
        else:
          self.setpos((x, y))
      except ZeroDivisionError, e:
        primo=1
        print "Probable asymptote for y =", y
      except ValueError, e:
        primo=1
        if definito:
          print "Defined from", inf_dom, "to", y
          definito=0
      except OverflowError, e:
        primo=1
    print "Defined from", inf_dom, "to", y

  def polar(self, f, max=360):
    """ro=f(th).

    example:
      >>> p=Plot()
      >>> p.axes(True)
      >>> p.polar("th", 720)
    """
    primo=1; definito=1; inf_dom=0; c=pi/180
    for i in range(0, max):
      th=i*c
      try:
        ro=eval(f)
        if primo:
          if not definito:
            inf_dom=th
            definito=1
          primo=0
          self.jump((ro*cos(th), ro*sin(th)))
        else:
          self.setpos((ro*cos(th), ro*sin(th)))
      except ZeroDivisionError, e:
        primo=1
        print "Probable point to the infinite for th =", th
      except ValueError, e:
        primo=1
        if definito:
          print "Defined from", inf_dom, "to", th
          definito=0
      except OverflowError, e:
        primo=1
    print "Defined from", inf_dom, "to", th

  def graphfile(self, nfsource):
    """Plot funtions written in file nfsource.

       example:
--cos.fun--8<------
# Tailor approsimation of y=cos(x)
s=(30, 30)
axes 1
y=cos(x)
y=1-(x**2)/2
y=1-(x**2)/2+(x**4)/24
y=1-(x**2)/2+(x**4)/24-(x**6)/720
----------->8------

      >>> p=Plot()
      >>> p.graphfile("cos.fun")
    """
    try:
      fs=open(nfsource,'r')
      while 1:
        riga=fs.readline()
        if not riga: break
        print riga,
        if riga[:2]=='y=':
          self.xy(riga[2:])
        elif riga[:2]=='x=':
          self.yx(riga[2:])
        elif riga[:3]=='ro=':
          self.polar(riga[3:])
        elif riga[0]=='#':
          pass
        elif riga[:2]=='s=':
          self.sets(eval(riga[2:]))
        elif riga[:5]=='reset':
          self.reset()
        elif riga[:4]=='axes':
          self.axes(int(riga[5:]))
    except IOError, e:
      if e.errno==13:
        print "Error:", e

if __name__=="__main__":
  p=Plot()
  p.axes(True)
  p.setcolor('navy')
  p.setwidth(2)
  p.xy(".2*x*x+2*x-3")
  p.setcolor('maroon')
  p.yx(".2*y*y+2*y-3")
  p.setcolor('gold')
  p.polar("th", 720)
  p.mainloop()
